using System;
using System.Runtime.InteropServices;

namespace Leap
{
	public class Pointable : Interface
	{
		public enum Zone
		{
			ZONE_NONE,
			ZONE_HOVERING,
			ZONE_TOUCHING,
			ZONENONE = 0,
			ZONEHOVERING,
			ZONETOUCHING
		}

		private HandleRef swigCPtr;

		public int Id => LeapPINVOKE.Pointable_Id_get(swigCPtr);

		public Hand Hand
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Pointable_Hand_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new Hand(intPtr, true);
			}
		}

		public Vector TipPosition
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Pointable_TipPosition_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new Vector(intPtr, true);
			}
		}

		public Vector TipVelocity
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Pointable_TipVelocity_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new Vector(intPtr, true);
			}
		}

		public Vector Direction
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Pointable_Direction_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new Vector(intPtr, true);
			}
		}

		public float Width => LeapPINVOKE.Pointable_Width_get(swigCPtr);

		public float Length => LeapPINVOKE.Pointable_Length_get(swigCPtr);

		public bool IsTool => LeapPINVOKE.Pointable_IsTool_get(swigCPtr);

		public bool IsFinger => LeapPINVOKE.Pointable_IsFinger_get(swigCPtr);

		public bool IsExtended => LeapPINVOKE.Pointable_IsExtended_get(swigCPtr);

		public bool IsValid => LeapPINVOKE.Pointable_IsValid_get(swigCPtr);

		public Zone TouchZone => (Zone)LeapPINVOKE.Pointable_TouchZone_get(swigCPtr);

		public float TouchDistance => LeapPINVOKE.Pointable_TouchDistance_get(swigCPtr);

		public Vector StabilizedTipPosition
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Pointable_StabilizedTipPosition_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new Vector(intPtr, true);
			}
		}

		public float TimeVisible => LeapPINVOKE.Pointable_TimeVisible_get(swigCPtr);

		public Frame Frame
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Pointable_Frame_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new Frame(intPtr, true);
			}
		}

		public static Pointable Invalid => new Pointable(LeapPINVOKE.Pointable_Invalid_get(), false);

		public Pointable(IntPtr cPtr, bool cMemoryOwn)
			: base(LeapPINVOKE.Pointable_SWIGUpcast(cPtr), cMemoryOwn)
		{
			swigCPtr = new HandleRef(this, cPtr);
		}

		public static HandleRef getCPtr(Pointable obj)
		{
			return obj?.swigCPtr ?? new HandleRef(null, IntPtr.Zero);
		}

		~Pointable()
		{
			Dispose();
		}

		public override void Dispose()
		{
			lock (this)
			{
				if (swigCPtr.Handle != IntPtr.Zero)
				{
					if (base.swigCMemOwn)
					{
						base.swigCMemOwn = false;
						LeapPINVOKE.delete_Pointable(swigCPtr);
					}
					swigCPtr = new HandleRef(null, IntPtr.Zero);
				}
				GC.SuppressFinalize(this);
				base.Dispose();
			}
		}

		public Pointable()
			: this(LeapPINVOKE.new_Pointable(), true)
		{
		}

		public bool Equals(Pointable arg0)
		{
			bool result = LeapPINVOKE.Pointable_Equals(swigCPtr, getCPtr(arg0));
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public override string ToString()
		{
			return LeapPINVOKE.Pointable_ToString(swigCPtr);
		}
	}
}
